package cn.jc.myfile.common.entity.result;

import lombok.Getter;
import lombok.Setter;

import java.beans.Transient;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;

/**
 * 执行结果封装
 */
@Getter
@Setter
public final class R<T> {
    /**
     * 编码
     */
    private long code;

    /**
     * 错误信息
     */
    private String message;

    /**
     * 返回数据
     */
    private T data;

    /**
     * 私有的空构造方法，防止空参数的new
     */
    private R() {
    }

    /**
     * 构造方法
     *
     * @param iCode {@link ICode}
     */
    public R(ICode iCode) {
        this(iCode, null);
    }

    /**
     * 构造方法（成功）
     *
     * @param data data
     */
    public R(T data) {
        this(RCode.SUCCESS, data);
    }

    /**
     * 构造方法
     *
     * @param iCode {@link ICode}
     * @param data  data
     */
    public R(ICode iCode, T data) {
        this.code = iCode.getCode();
        this.message = iCode.getMessage();
        this.data = data;
    }

    /**
     * success 方法
     *
     * @param <T> t
     * @return 返回成功
     */
    public static <T extends Serializable> R<T> success() {
        return new R<>(RCode.SUCCESS);
    }

    /**
     * success 方法
     *
     * @param t   t
     * @param <T> t
     * @return 返回成功
     */
    public static <T extends Serializable> R<T> success(T t) {
        return new R<>(t);
    }

    /**
     * fail 方法
     *
     * @param <T> t
     * @return 返回失败
     */
    public static <T extends Serializable> R<T> fail() {
        return new R<>(RCode.FAILED);
    }

    /**
     * fail 方法
     *
     * @param t   t
     * @param <T> t
     * @return 返回失败
     */
    public static <T extends Serializable> R<T> fail(T t) {
        return new R<>(RCode.FAILED, t);
    }

    /**
     * fail 方法
     *
     * @param message message
     * @return 返回失败
     */
    public static <T extends Serializable> R<T> fail(String message) {
        R<T> r = new R<>(RCode.FAILED);
        r.setMessage(message);
        return r;
    }

    /**
     * fail 方法
     * <p>
     * 前台不全局弹窗提示
     *
     * @param message message
     * @return 返回失败
     */
    public static <T extends Serializable> R<T> silenceFail(String message) {
        R<T> r = new R<>(RCode.SILENCE_FAILED);
        r.setMessage(message);
        return r;
    }

    /**
     * 判断是否成功
     *
     * @return 成功
     */
    public boolean succeed() {
        return RCode.SUCCESS.getCode() == this.code;
    }

    /**
     * 请求成功，且返回结果为true
     *
     * @return 请求结果
     */
    @Transient
    public boolean isTrue() {
        if (notNull() && this.data instanceof Boolean) {
            return ((Boolean) this.data).booleanValue();
        }
        return false;
    }

    /**
     * 请求失败，或者请求结果为null
     *
     * @return 请求结果
     */
    @Transient
    public boolean isNull() {
        return !notNull();
    }

    /**
     * 请求成功，且数据不为null
     *
     * @return 请求结果
     */
    public boolean notNull() {
        return succeed() && this.data != null;
    }

    /**
     * 请求失败，或者集合为empty
     *
     * @return 请求结果
     */
    @Transient
    public boolean isEmpty() {
        return !notEmpty();
    }

    /**
     * 请求成功，且集合非empty
     *
     * @return 请求结果
     */
    public boolean notEmpty() {
        if (notNull()) {
            if (this.data instanceof Collection) {
                Collection<?> collection = (Collection<?>) this.data;
                return !collection.isEmpty();
            } else if (this.data instanceof Map) {
                Map<?, ?> map = (Map<?, ?>) this.data;
                return !map.isEmpty();
            } else {
                throw new UnsupportedOperationException("无法对非集合或map类型进行判断");
            }
        }
        return false;
    }

    @Override
    public String toString() {
        return String.format("[返回码:%s,返回信息:%s]", this.code, this.message);
    }
}
